fix(config): apply ipv4_only IPv6 mode so TUN doesn't hijack the default IPv6 route - #140
Conversation
…ult IPv6 route The ipv6-mode: ipv4_only option was parsed but never applied. setInbound() used isIPv6Supported() - which only resolves the IPv6 loopback and therefore succeeds on virtually any host - instead of the user's IPv6Mode. As a result the TUN always received an IPv6 address and auto_route captured the default IPv6 route, and inbounds bound to ::, regardless of the IPv4-only choice. On hosts without global IPv6 this black-holes every AAAA-first connection (e.g. yandex.ru fails while curl -4 works). Verified by building the patched core and running it under Hiddify 4.1.1: with ipv4_only the TUN is now generated IPv4-only and AAAA sites load correctly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
061f87b to
275cde0
Compare
Evidence for hiddify/hiddify-core PR #140Independent reproduction with Hiddify app 4.1.1 / released core v4.1.0 on Windows, plus a WPS Office desktop failure that is consistent with this change. Deterministic configuration-only reproductionThis does not require a real subscription or a working server. It only builds configuration; it does not start TUN or change system networking.
{"outbounds":[{"type":"socks","tag":"documentation-only","server":"192.0.2.1","server_port":1080}]}
{"ipv6-mode":"ipv4_only","enable-tun":true,"remote-dns-address":"1.1.1.1","direct-dns-address":"1.1.1.1","mixed-port":12334,"mtu":1500,"tun-implementation":"system","region":"other"}Run the core's import ctypes, sys
dll = ctypes.CDLL(sys.argv[1])
cli = dll.parseCli
cli.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)]
cli.restype = ctypes.c_char_p
args = [b"HiddifyCli"] + [x.encode("utf-8") for x in sys.argv[2:]]
argv = (ctypes.c_char_p * len(args))(*args)
result = cli(len(args), argv)
if result:
print(result.decode("utf-8", errors="replace"))The released DLL actually generated these inbounds (excerpt): [
{"type":"tun","tag":"tun-in","address":["172.19.0.1/28","fdfe:dcba:9876::1/126"],"auto_route":true},
{"type":"mixed","tag":"mixed-in::1","listen":"::1"},
{"type":"mixed","tag":"mixed-in127.0.0.1","listen":"127.0.0.1"}
]Expected with explicit Real application evidence
There is a related Windows report at hiddify/hiddify-app#2307, closed by Scope and suggested regression coverageI verified the released-core failure and the adapter-only workaround, not a build of this PR. No claim here that this PR has passed Windows integration tests on my machine. The guard in this PR addresses the configuration error reproduced above. A regression test for An additional ChatGPT desktop failure during this investigation came from a local stale |
Problem
ipv6-mode: ipv4_onlyis parsed but never applied. Selecting "IPv4 only" has no effect on the generated sing-box config.Root cause
In
v2/config/builder.go,setInbound()derives IPv6 usage fromisIPv6Supported()instead of the user'sIPv6Mode. The code that would applyIPv6Modeis commented out (lines ~434-439 and ~459-469).isIPv6Supported()only resolves the IPv6 loopback:which succeeds on virtually any host — even one with no global IPv6. So
ipv6Enableis effectively alwaystrue: the TUN always receives an IPv6 address,auto_routecaptures the default IPv6 route, and inbounds bind to::— regardless of the IPv4-only choice.On hosts without global IPv6, browsers try AAAA first (Happy Eyeballs); packets enter the TUN but egress has no usable IPv6, so the TLS handshake is dropped (
ERR_CONNECTION_CLOSED). Example:yandex.ru(routed.ru -> direct) fails over IPv6 whilecurl -4succeeds. The only workaround is disabling IPv6 OS-wide.Fix
Same conversion pattern already used in
hiddify_option.go.Verified (built and tested, not just theory)
Built this patch into
hiddify-core.dll(from the v4.1.0 tree, Windows/amd64) and ran it under the installed Hiddify 4.1.1 on Windows 11, withipv6-mode: ipv4_onlyand TUN enabled.Before (stock core) — generated
current-config.json:After (patched core) — same settings:
Result: sites with AAAA records (e.g.
yandex.ru) now load correctly over IPv4 through the TUN, with no OS-level IPv6 workaround needed.Bonus: this also fixes
failed to start background coreon hosts where IPv6 is disabled OS-wide — the core no longer tries to bind::or assign an IPv6 address to the TUN.Notes
resolve-destination— worth restoring separately.dns.strategy: ipv4_only;getDNSServerOptionscurrently hardcodesprefer_ipv4, which does not drop AAAA.Related: hiddify/hiddify-app#2172 (same symptom — same version, same
ipv4_only, sites failing in VPN mode — reported without the IPv6 diagnosis).